Skip to content

[sandbox audit] README: state the real security model and its known limitations - #15

Draft
Wauplin wants to merge 1 commit into
mainfrom
security/sandbox-docs-accuracy
Draft

[sandbox audit] README: state the real security model and its known limitations#15
Wauplin wants to merge 1 commit into
mainfrom
security/sandbox-docs-accuracy

Conversation

@Wauplin

@Wauplin Wauplin commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

[sandbox audit] — PR 1 of 13 in this repo's stack; merge in order.
Next: #16
Review only the commits this PR adds on top of its base; bases collapse to main as the stack lands.

Why

An internal security review of the Sandbox API found gaps between what the docs promise and
what the server delivers. The code fixes follow as separate PRs; this documents the current
state first, so nobody deploys host mode on the strength of a guarantee it does not provide.

No code change.

What changed

Token scope. SBX_TOKEN is one token per server process, not per sandbox. In dedicated
mode the job is the sandbox so the two coincide; in host mode the same value authorizes every
/v1/sandboxes/{id}/* route for every sandbox plus the pool-management routes, so a leak is
host-wide. Said so explicitly.

New "Known limitations" section listing what is currently unhardened in host mode:

  • both route surfaces are always registered, so /v1/exec and friends stay live in host mode
    and run as the server's root identity (and /v1/sandboxes* stays live in dedicated mode)
  • the file API resolves paths lexically, then follows symlinks with root privileges
  • the port proxy connects <home>/.sbx/proxy/<port>.sock by name, without O_NOFOLLOW or
    SO_PEERCRED, and does not validate <port> in host mode
  • auth fails open when SBX_TOKEN is unset or empty
  • Landlock fails open, and ABI 1 is accepted although the documented guarantees need ABI 4
    (TCP bind) and ABI 6 (abstract-socket scoping)
  • caller-supplied max_procs/max_mem_mb are unclamped and the memory multiplication is not
    checked_mul; an invalid SBX_CAPACITY becomes usize::MAX
  • the HTTP front end has no read deadlines or connection cap, overwrites duplicate headers,
    treats an invalid Content-Length as zero, and authenticates a hijacked proxy connection
    only once
  • DELETE /v1/processes/{id} answers 200 for an unknown id
  • process supervision gaps: timeout watchers sleeping past child exit and then signalling a
    raw pid, foreground commands invisible to the idle watchdog, setsid survivors, unreaped
    orphans at PID 1, non-recycled uids (~45k creations per host lifetime)
  • /health is unauthenticated; sandbox ids fall back to a timestamp if /dev/urandom fails

Also flagged the two places in the existing text that read as stronger guarantees than they
are: the SBX_TOKEN row in the configuration table, and the host-mode file-path paragraph.

Companion

huggingface/huggingface_hub#4831 does the same for the user-facing docs.

Follow-ups

Each hardening PR should delete its entry here, so the section doubles as the remediation
tracker. Next up: the file API and port-proxy symlink handling, then route-surface separation
and fail-closed auth.

An internal security review found gaps between what the README promises and
what the server delivers. The code fixes follow as separate PRs; this
documents the current state first, so nobody deploys host mode on the
strength of a guarantee it does not provide.

- SBX_TOKEN is one token per server process, not per sandbox. In host mode
  it authorizes every /v1/sandboxes/{id}/* route for every sandbox plus the
  pool-management routes, so a leak is host-wide. Said so explicitly, and
  flagged the fail-open case in the configuration table.
- The host-mode file-path paragraph implied a confined path; the rooting is
  lexical, not symlink-proof. Pointed it at the new section.
- Added a "Known limitations" section: both route surfaces always
  registered, the file API and port proxy following symlinks as root,
  fail-open auth, fail-open Landlock and ABI 1 acceptance, unclamped
  caller-supplied limits and the unchecked memory multiplication, the HTTP
  front end's missing deadlines/caps and lax parsing, DELETE /processes
  answering 200 for an unknown id, the process-supervision gaps, and the
  unauthenticated /health plus the non-CSPRNG id fallback.

No code change. Each subsequent hardening PR should delete its entry from
that section, so it doubles as the remediation tracker.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Wauplin
Wauplin marked this pull request as draft September 8, 2026 13:07
@Wauplin Wauplin changed the title README: state the real security model and its known limitations [sandbox audit] README: state the real security model and its known limitations Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant